﻿#ifndef QFTPDTP_H
#define QFTPDTP_H
#include"XQNework.h"
#include"XQUrlInfo.h"
#include<QTcpServer>
#include<QTcpSocket>
/*
  QFtpDTP (DTP =数据传输过程)控制客户端和服务器之间的所有客户端数据传输。
*/
class XQFtpPI;
class XQFtpDTP : public QObject
{
    Q_OBJECT
public:
    friend class XQFtp;
    enum ConnectState {
        CsHostFound,// 主机已找到
        CsConnected,// 已连接
        CsClosed,// 已关闭
        CsHostNotFound,// 未找到主机
        CsConnectionRefused // 连接被拒绝
    };

    XQFtpDTP(XQFtpPI* p, QObject* parent = 0);

    void setData(QByteArray*);
    void setDevice(QIODevice*);
    void writeData();
    //设置数据字节大小
    void setBytesTotal(qint64 bytes);
    void setDebug(int* debug);
    //是否是指定Debug模式
    bool isDebugModel(Ftp::Debug model);
    //设置缓冲块大小
    void setBlockSize(qint64 size);

    bool hasError() const;
    QString errorMessage() const;
    void clearError();

    void connectToHost(const QString& host, quint16 port);
    int setupListener(const QHostAddress& address);
    void waitForConnection();

    QTcpSocket::SocketState state() const;
    qint64 bytesAvailable() const;
    qint64 read(char* data, qint64 maxlen);
    QByteArray readAll();

    void abortConnection();

    static bool parseDir(const QByteArray& buffer, const QString& userName, XQUrlInfo* info);

signals:
    //获取文件列表信息
    void listInfo(const XQUrlInfo&);
    //准备读取
    void readyRead();
    //传输进度
    void dataTransferProgress(qint64, qint64);
    //连接状态
    void connectState(int);
    //结束了(读写)
    void finished();
private slots:
    void socketConnected();
    void socketReadyRead();
    void socketError(QAbstractSocket::SocketError);
    void socketConnectionClosed();
    void socketBytesWritten(qint64);
    //有新的客户端连接
    void setupSocket();

    void dataReadyRead();

private:
    void clearData();
    int* m_debug = nullptr;//调试模式
    QTcpSocket* m_socket=nullptr;
    QTcpServer m_listener;

    XQFtpPI* m_pi=nullptr;
    QString m_err;
    qint64 m_blockSize = 0;//缓冲块大小
    char* m_buffer = nullptr;//缓冲区
    qint64 m_bytesDone;//当前数据字节大小
    qint64 m_bytesTotal;//当前数据总字节数
    bool m_callWriteData;

    // 如果is_ba为true，则使用ba;ba不等于0。
    // 否则使用dev;dev可以是0也可以不是。
    union {
        QByteArray* ba;
        QIODevice* dev;
    } m_data;
    bool m_is_ba; //是否是QByteArray

    QByteArray m_bytesFromSocket;//socket的缓冲区
};
#endif // !QFtpPrivate_H
